#ifndef Processes_H
#define Processes_H

#define null NULL
#include <process.h>
#include <QMessageBox>
#include <QPainter>
#include <QList>
#include <QtDebug>


class Processes
{
    public:

        Proces *head;
        QPainter *q;
        int pIna;
        int pSus;
        int pPre;
        int gg;
        Proces *executed;


        //----------------------------------------------------------------------------
        Processes(){
            pIna=0;
            pSus=0;
            pPre=0;
            head=NULL;
            executed=NULL;
            gg=0;
        }

        //----------------------------------------------------------------------------
        void setPainter(QPainter *q){
            this->q=q;
        }

        //----------------------------------------------------------------------------
        void add(Proces * r){
            Proces * aux = head;
            Proces * ant = NULL;

            if(aux==NULL){
                head = r;
            }
            else{
                while(aux){
                    //qDebug()<<aux->compareTo(r);
                    //if(r->priority <= aux->priority){
                    if(aux->compareTo(r)==1){
                        if(aux== head){
                            r->next = head;
                            head = r;
                            break;
                        }
                        else{

                           ant->next = r;
                           r->next = aux;
                           break;
                        }

                    }else{
                        if(!aux->next){
                            aux->next=r;
                            break;
                        }
                    }

                    ant = aux;
                    aux = aux->next;
                }
            }
        }


        //----------------------------------------------------------------------------
        int size(){
            int s=0;
            Proces *aux=head;
            while(aux){
                s++;
                aux=aux->next;
            }
            return s;
        }


        //----------------------------------------------------------------------------
        Proces * elementAt(int p){
            Proces *aux=head;
            int counter=0;
            if(head){
                while(aux){
                    if(counter==p)	return aux;
                    aux=aux->next;
                    counter++;
                }
            }

            return NULL;
        }

        //----------------------------------------------------------------------------
        Proces * getMinpriority(){
            Proces *h=head;
            while(h){
                if(h->state=="Preparado") return h;
                h=h->next;
            }
            return NULL;
        }

        //----------------------------------------------------------------------------
        Proces * remove(int p){
            if(head!=NULL){//verificamos que exista un elemento
                Proces *aux=head, *q=NULL;
                int counter=0;
                while(aux!=NULL){
                    if(counter==p){
                        //primer caso para remover el primer elemento
                        if(aux==head) head=aux->next;
                        //segundo caso para eliminar otro elemento
                        else q->next=aux->next;
                        counter++;
                        return aux;
                    }
                    else{
                        q=aux;
                        aux=aux->next;
                        counter++;
                    }
                }
            }

            return NULL;
        }

        //----------------------------------------------------------------------------
        ~Processes(){
            Proces *h=head;
            while(h){
                Proces *g=h;
                h=h->next;
                delete(g);
            }
        }

        //----------------------------------------------------------------------------
        void paintProcesses(int i){
            if(gg%2==0){
                QPen pen(Qt::white, 2, Qt::SolidLine);
                q->setPen(pen);
                pIna=70;
                pPre=180;
                pSus=70;
                if(i==1){
                    paintPreparated(q);
                    paintInactives(q);

                }else if(i==2)
                    paintPreparated(q);
                else if(i!=0){

                    Proces *em=getMinpriority();

                    Proces * g=head;
                    int s=0;
                    while(g){
                        if(g->quantum==0) this->remove(s);
                        else if(g->state=="Suspendido" && g->inter==0) g->state="Preparado";
                        else if(g->state=="Suspendido" && g->inter==1){
                            if(g->ya==0)g->ya=1;
                            else{
                                g->state="Preparado";
                                g->ya=0;
                            }
                        }
                        g=g->next;
                        s++;
                    }

                    Proces *e=getExecutedProcess();
                    if(e){
                        e->quantum--;
                        e->state="Suspendido";
                    }


                    if(em)
                        em->state="Ejecucion";


                    sort();

                    printSuspended(q);

                    printExecuted(q);

                    paintPreparated(q);


                }

            }
            gg++;
        }

        //----------------------------------------------------------------------------
        void paintInactives(QPainter *q){

            Proces *h=head;

            while(h){
                if(h->state=="Inactivo"){
                    pIna+=20;
                    q->drawText( QPoint( 80,pIna),h->name);
                    prepareProcess(h);
                }
                h=h->next;
            }
        }

        //----------------------------------------------------------------------------
        void paintPreparated(QPainter *q){
            Proces *h=head;

            while(h){
                if(h->state=="Preparado"){
                    pPre+=20;
                    q->drawText(  QPoint( 280,pPre),h->name);
                }
                h=h->next;
            }
        }
        //----------------------------------------------------------------------------
        void printExecuted(QPainter *q){

            Proces *h=head;

            while(h){
                if(h->state=="Ejecucion"){
                    pPre+=20;
                    q->drawText(QPoint( 280,10),h->name);
                }
                h=h->next;
            }
        }

        //----------------------------------------------------------------------------
        void printSuspended(QPainter *q){
            Proces *h=head;

            while(h){
                if(h->state=="Suspendido"){
                    pSus+=20;
                    q->drawText(QPoint( 480,pSus),h->name);

                }
                h=h->next;
            }
        }

        //----------------------------------------------------------------------------
        void prepareProcess(Proces *h){
            h->state="Preparado";
        }

        //----------------------------------------------------------------------------
        Proces * getExecutedProcess(){
            Proces *h=head;

            while(h){
                if(h->state=="Ejecucion")
                    return h;

                h=h->next;
            }

            return NULL;
        }

        //----------------------------------------------------------------------------
        void sort(){
            Proces * head2=NULL;
            Proces * h=head;

            while(h){
                Proces * aux = head2;
                Proces * ant = NULL;
                Proces *r=new Proces(h->priority,h->quantum,h->pid,h->inter);
                r->state=h->state;
                r->ya=h->ya;
                if(aux==NULL){
                    head2 = r;
                }else{
                    while(aux){
                        if(aux->compareTo(r)==1){
                            if(aux== head2){
                                r->next = head2;
                                head2 = r;
                                break;
                            }
                            else{

                               ant->next = r;
                               r->next = aux;
                               break;
                            }

                        }else{
                            if(!aux->next){
                                aux->next=r;
                                break;
                            }
                        }

                        ant = aux;
                        aux = aux->next;
                    }
                }
                h=h->next;
            }

            head=head2;
        }
};

#endif // PROCESS_H
